package org.springblade.dev.template;

import cn.hutool.core.collection.ListUtil;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.builder.CustomFile;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.fill.Property;
import lombok.extern.log4j.Log4j2;

import java.util.List;
import java.util.Map;
import java.util.Properties;

/**
 * 保留版权 : CopyRright (c) 2024-2024 于继业 版权所有
 * 文件名称 : BootGenerator
 * 文件编号 : 1-1-1
 * 文件版本 : 2024-01-18.01
 * 创建日期 : 2024-01-18
 * 修改人名 :
 * 修改日期 :
 * 功能描述 :
 *
 * @author 于继业
 */
@Log4j2
public class CloudGenerator extends BaseGenerator {
    // 父包名
    private final static String PARENT_PACKAGE = "org.springblade.modules";
    // 属性中作者的名字
    private final static String AUTHOR_NAME = "author";

    @Override
    public GlobalConfig globalConfig(String projectRootPath, Properties props) {
        return new GlobalConfig.Builder()
                // 作者
                .author(props.getProperty(AUTHOR_NAME))
                // 生成文件输出路径(写到java目录)
                .outputDir(projectRootPath + "/src/main/java")
                // 开启swagger
                .enableSwagger()
                // 注释日期格式
                .commentDate("yyyy-MM-dd")
                // 覆盖文件(需谨慎使用)
                .fileOverride()
                // 设置时间对应类型
                .dateType(DateType.ONLY_DATE)
                // 生成后不要打开目录
                .disableOpenDir()
                .build();
    }

    @Override
    public PackageConfig packageConfig(String moduleName) {
        return new PackageConfig.Builder()
                // Controller 包名
                .controller("controller")
                // Service 包名
                .service("service")
                // Service Impl 包名
                .serviceImpl("service.impl")
                // Entity 包名
                .entity("entity")
                // Mapper 包名
                .mapper("mapper")
                // Mapper XML 包名
                .xml("mapper")
                // 自定义文件包名
                //.other("")
                // 路径配置信息
                // .pathInfo( Collections.singletonMap(OutputFile.mapperXml, projectPath + "/src/main/resources/mapper/" + moduleName))
                // 父包名
                .parent(PARENT_PACKAGE)
                // 父包模块名
                .moduleName(moduleName)
                .build();
    }

    @Override
    public TemplateConfig templateConfig() {
        return new TemplateConfig.Builder()
                // 禁用所有模板
                //.disable()
                // 禁用模板
                // .disable(TemplateType.ENTITY)
                // 设置实体模板路径(kotlin)
                //.entityKt("")
                // 设置实体模板路径(JAVA)
                // .entity("/boot/entity.java")
                // 设置 service 模板路径
                .service("/boot/service.java")
                // 设置 serviceImpl 模板路径
                .serviceImpl("/boot/serviceImpl.java")
                // 设置 mapper 模板路径
                .mapper("/boot/mapper.java")
                // 设置 mapperXml 模板路径
                .xml("/boot/mapper.xml")
                // 设置 controller 模板路径
                .controller("/boot/controller.java")
                .build();
    }

    @Override
    public InjectionConfig injectionConfig(Map<String, Object> customMap, String packageWebDir, String serviceName) {
        customMap.put("servicePackage", PARENT_PACKAGE);
        customMap.put("servicePackageLowerCase", PARENT_PACKAGE.toLowerCase());

        List<CustomFile> customFileList = ListUtil.toList(
                new CustomFile.Builder().fileName("VO.java").templatePath("/boot/entityVO.java.vm").packageName("vo").build(),
                new CustomFile.Builder().fileName("Criteria.java").templatePath("/boot/criteria.java.vm").packageName("criteria").build(),
                new CustomFile.Builder().fileName("DTO.java").templatePath("/boot/entityDTO.java.vm").packageName("dto").build(),
                new CustomFile.Builder().fileName("Form.java").templatePath("/boot/form.java.vm").packageName("form").build(),
                new CustomFile.Builder().fileName("Wrapper.java").templatePath("/boot/wrapper.java.vm").packageName("wrapper").build()
        );
        return new InjectionConfig.Builder()
                // 输出文件之前消费者
                .beforeOutputFile((tableInfo, objectMap) -> log.info("tableInfo: " + tableInfo.getEntityName() + " objectMap: " + objectMap.size()))
                // 自定义配置 Map 对象
                // Collections.singletonMap("test", "baomidou")
                .customMap(customMap)
                // 自定义配置模板文件
                // Collections.singletonMap("test.txt", "/templates/test.vm") 方法 formatNameFunction 可以格式化文件，
                // 参考测试用例 H2CodeGeneratorTest.testCustomFileByList
                // https://github.com/baomidou/generator/blob/develop/mybatis-plus-generator/src/test/
                // java/com/baomidou/mybatisplus/generator/samples/H2CodeGeneratorTest.java
                .customFile(customFileList)
                .build();
    }

    @Override
    public StrategyConfig strategyConfig(String offSetTablePrefix, List<String> tables, String[] superEntityColumns) {
        return new StrategyConfig.Builder()
                // 需要抵消的表前缀
                .addTablePrefix(offSetTablePrefix)
                // 设置生成需要映射的表名
                .addInclude(tables)
                // 策略开启⼤写命名
                //.enableCapitalMode()
                // 构建Service层 ---------------------------------
                .serviceBuilder()
                // 业务层接口类命名
                .formatServiceFileName("I%sService")
                // 业务层接口实现类命名
                .formatServiceImplFileName("%sServiceImpl")
                // 构建实体类 ---------------------------------
                .entityBuilder()
                // 字段名驼峰命名
                .columnNaming(NamingStrategy.underline_to_camel)
                // 表名驼峰命名
                .naming(NamingStrategy.underline_to_camel)
                // 设置文件名
                // .formatFileName("%sEntity")
                // 添加lombock的getter、setter注解
                .enableLombok()
                // 启动链式写法@Accessors(chain = true)
                .enableChainModel()
                // 启动属性转常量功能@FieldNameConstants
                .enableColumnConstant()
                // 逻辑删除字段，标记@TableLogic
                .logicDeleteColumnName("deleted")
                // 启动字段注解
                .enableTableFieldAnnotation()
                // 属性值填充策略
                .addTableFills(ListUtil.toList(
                        new Property("createDate", FieldFill.INSERT),
                        new Property("updateDate", FieldFill.INSERT_UPDATE)
                ))
                // 构建Controller类 ---------------------------------
                .controllerBuilder()
                // 映射路径使用连字符格式，而不是驼峰
                .enableHyphenStyle()
                // Controller类命名
                .formatFileName("%sController")
                // Controller 类继承 BaseController
                .superClass("org.springblade.core.boot.ctrl.BladeController")
                // 标记@RestController注解
                .enableRestStyle()
                // 构建mapper接口类 ---------------------------------
                .mapperBuilder()
                // 生成基本的resultMap
                .enableBaseResultMap()
                // Mapper接口类明名
                .formatMapperFileName("%sMapper")
                // Mapper接口类集成 BaseMapper
                .superClass(BaseMapper.class)
                // 标记@Mapper注解
                .enableMapperAnnotation()
                // Mapper.xml命名
                .formatXmlFileName("%sMapper")
                // 生成基本的SQL片段
                .enableBaseColumnList()
                .build();
    }
}
